package com.sinszm.web.socket;

import com.sinszm.common.exception.ApiException;
import com.sinszm.web.properties.WebSocketProperties;
import com.sinszm.web.support.WebError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.web.socket.*;

/**
 * WebSocket消息处理器
 *
 * @author chenjianbo
 */
public class MWebSocketHandler implements WebSocketHandler {

    private ApplicationContext context;
    private WebSocketProperties properties;
    private ImProcessor imProcessor;

    private static final Logger logger = LoggerFactory.getLogger(MWebSocketHandler.class);

    public MWebSocketHandler(ApplicationContext context, WebSocketProperties properties) {
        this.context = context;
        this.properties = properties;
    }

    /**
     * 连接成功，校验扩展插槽
     * @param session   通道
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        Class<? extends ImProcessor> clz = properties.getProcessor();
        if (clz == null) {
            logger.error(new ApiException(WebError.WEB_ERROR_003).toString());
            return;
        }
        try {
            imProcessor = context.getBean(clz);
        } catch (BeansException e) {
            logger.error(new ApiException(WebError.WEB_ERROR_004).toString());
            return;
        }
        WsCache.getInstance().put(session.getId(), session);
        //处理离线消息
        imProcessor.open(session);
    }

    /**
     * 接收与发送消息
     * @param session   通道
     * @param message   消息
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
        WebSocketSession wss = WsCache.getInstance().get(session.getId());
        if (wss == null) {
            ImProcessor.sendError(session, CloseStatus.SERVER_ERROR, WebError.WEB_ERROR_005);
            return;
        }
        if (message instanceof BinaryMessage) {
            imProcessor.message(wss, (BinaryMessage) message);
        } else {
            ImProcessor.sendError(wss, CloseStatus.PROTOCOL_ERROR, WebError.WEB_ERROR_002);
        }
    }

    /**
     * 异常
     * @param session       通道
     * @param exception     异常信息
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        WsCache.getInstance().clean(session.getId());
        if (session.isOpen()) {
            ImProcessor.sendError(session, CloseStatus.SERVER_ERROR, WebError.WEB_ERROR_006);
        }
        logger.error("WS异常信息：", exception);
    }

    /**
     * 连接关闭
     * @param session       关闭
     * @param closeStatus   关闭代码
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
        WsCache.getInstance().clean(session.getId());
        if (imProcessor != null) {
            imProcessor.closed(
                    session,
                    closeStatus
            );
        }
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

}
